package com.fenfen.novel.fragment;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v4.util.Pair;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;

import com.fenfen.novel.NovelActivity;
import com.fenfen.novel.R;
import com.fenfen.novel.adapter.NovelAdapter;
import com.fenfen.novel.model.Novel;
import com.fenfen.novel.rest.RestClient;
import com.fenfen.novel.utils.CommonUtil;

import org.parceler.Parcels;

import java.util.ArrayList;
import java.util.List;

import jp.wasabeef.recyclerview.adapters.SlideInBottomAnimationAdapter;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class NovelListFragment extends Fragment implements NovelAdapter.NovelItemClickListener, Callback<List<Novel>> {

  private static String Tag = NovelListFragment.class.getSimpleName();
  public static final String EXTRA_DATA_TYPE = "data_type";

  public static final String EXTRA_TOP_TYPE = "top_type";
  public static final String EXTRA_CATEGORY_ID = "category_id";
  public static final String EXTRA_SEARCH_KEY = "search_key";

  private NovelAdapter adapter;
  private List<Novel> novelList = new ArrayList<>();

  private SwipeRefreshLayout swipeRefresh;
  private byte dataType;
  private byte topType;
  private int categoryId;
  private String searchKey;

  private Call<List<Novel>> call;

  private int nextLoadPage;
  private boolean isLoading;

  public static NovelListFragment newInstance(Bundle bundle) {
    NovelListFragment novelTopFragment = new NovelListFragment();
    novelTopFragment.setArguments(bundle);
    novelTopFragment.setRetainInstance(true);
    return novelTopFragment;
  }

  @Override
  public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    initIntentData();
  }

  private void initIntentData() {
    dataType = getArguments().getByte(EXTRA_DATA_TYPE, CommonUtil.NovelListType.TYPE_NOVEL_TOP);
    Log.d(Tag, "dataType=" + dataType);
    if (dataType == CommonUtil.NovelListType.TYPE_NOVEL_TOP) {
      topType = getArguments().getByte(EXTRA_TOP_TYPE, CommonUtil.NovelTopType.DEFAULT);
    } else if (dataType == CommonUtil.NovelListType.TYPE_NOVEL_CATEGORY) {
      categoryId = getArguments().getInt(EXTRA_CATEGORY_ID, CommonUtil.NONE_INT_DATA);
    } else if (dataType == CommonUtil.NovelListType.TYPE_NOVEL_SEARCH) {
      searchKey = getArguments().getString(EXTRA_SEARCH_KEY);
    }
  }

  private void cancelRequest() {
    if (call != null && call.isExecuted() && !call.isCanceled()) {
      call.cancel();
    }
  }

  private boolean isRequest() {
    return call != null && call.isExecuted();
  }

  private void loadNovelTopList(byte loadTopType) {
    loadNovelTopList(loadTopType, nextLoadPage);
  }

  private void loadNovelTopList(byte loadTopType, int page) {
    //set default topType
    topType = (loadTopType == 0) ? CommonUtil.NovelTopType.DEFAULT : loadTopType;
    Log.d(Tag, "loadNovelTopList with topType=" + topType);
    call = RestClient.newInstance().getNovelService().showNovelsByTopAndPage(topType, page);
    call.enqueue(this);
  }

  private void setSwipeRefresh(boolean isRefreshing) {
    if (swipeRefresh != null) {
      swipeRefresh.setRefreshing(isRefreshing);
    }
  }

  private void resetFirstRequestState() {
    if (isRequest()) {
      cancelRequest();
    }
    nextLoadPage = CommonUtil.FIRST_PAGE;
    setLoading(true);
    adapter.clearData();
    adapter.setHasLoadingMore(true);
  }

  public void loadData() {
    resetFirstRequestState();
    if (dataType == CommonUtil.NovelListType.TYPE_NOVEL_TOP) {
      setSwipeRefresh(true);
      loadNovelTopList(topType);
    } else if (dataType == CommonUtil.NovelListType.TYPE_NOVEL_CATEGORY) {
      setSwipeRefresh(true);
      loadCategoryNovelList(categoryId);
    } else if (dataType == CommonUtil.NovelListType.TYPE_NOVEL_SEARCH) {
      if (!TextUtils.isEmpty(searchKey)) {
        swipeRefresh.setEnabled(true);
        setSwipeRefresh(true);
      } else {
        swipeRefresh.setEnabled(false);
      }
      loadSearchNovelList(searchKey);
    } else {
      setSwipeRefresh(false);
    }
  }

  private void loadSearchNovelList(String searchKey) {
    loadSearchNovelList(searchKey, nextLoadPage);
  }

  private void loadSearchNovelList(String searchKey, int page) {
    if (TextUtils.isEmpty(searchKey)) {
      setSwipeRefresh(false);
      return;
    }
    call = RestClient.newInstance().getNovelService().searchNovelsByPage(searchKey, page);
    call.enqueue(this);
  }

  public void loadCategoryNovelList(int categoryId) {
    loadCategoryNovelList(categoryId, nextLoadPage);
  }

  private void loadCategoryNovelList(int categoryId, int page) {
    if (categoryId == CommonUtil.NONE_INT_DATA) {
      return;
    }
    call = RestClient.newInstance().getNovelService().showNovelsByCategoryIdAndPage(categoryId, page);
    call.enqueue(this);
  }

  public boolean isLoading() {
    return isLoading;
  }

  public void setLoading(boolean loading) {
    isLoading = loading;
  }

  @Nullable
  @Override
  public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_top, container, false);
    swipeRefresh = (SwipeRefreshLayout) view.findViewById(R.id.swiperefresh);
    swipeRefresh.setColorSchemeColors(CommonUtil.resolveColor(getActivity(), R.attr.colorPrimary, android.R.color.holo_blue_light), ContextCompat.getColor(getActivity(), android.R.color.holo_red_light));
//    swipeRefresh.setColorSchemeResources(CommonUtil.resolveColor(getActivity(), R.attr.colorPrimary, android.R.color.holo_blue_light), android.R.color.holo_red_light);
    swipeRefresh.setOnRefreshListener(new MyOnRereshListener());
//    swipeRefresh.setRefreshing(true);
    swipeRefresh.post(new Runnable() {
      @Override
      public void run() {
//        swipeRefresh.setRefreshing(true);
        loadData();
      }
    });
    RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
    LinearLayoutManager lm = new LinearLayoutManager(getActivity());
    adapter = new NovelAdapter(getActivity(), novelList);
    recyclerView.setLayoutManager(lm);

    SlideInBottomAnimationAdapter animationAdapter = new SlideInBottomAnimationAdapter(adapter);
    animationAdapter.setDuration(500);
    animationAdapter.setInterpolator(new AccelerateDecelerateInterpolator());
    recyclerView.setAdapter(animationAdapter);
    recyclerView.addOnScrollListener(new MyOnScrollListener());
    adapter.setItemClickListener(this);

    return view;
  }

  public void setTopType(byte topType) {
    this.topType = topType;
  }

  public byte getTopType() {
    return topType;
  }

  @Override
  public void onItemClick(View v, Novel novel) {
    Intent intent = new Intent(getContext(), NovelActivity.class);
    intent.putExtra(NovelActivity.EXTRA_NOVEL_ENTITY, Parcels.wrap(novel));
    ActivityOptionsCompat activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(
        getActivity(),
        new Pair<>(v.findViewById(R.id.novel_img),
            NovelActivity.VIEW_NAME_HEADER_IMAGE));

    // Now we can start the Activity, providing the activity options as a bundle
    ActivityCompat.startActivity(getActivity(), intent, activityOptions.toBundle());
  }

  @Override
  public void onResponse(Call<List<Novel>> call, Response<List<Novel>> response) {
    setLoading(false);
    setSwipeRefresh(false);

    if (response.isSuccessful()) {
      List<Novel> list = response.body();
      if (list == null || list.size() == 0) {
        if (adapter != null) {
          adapter.setHasLoadingMore(false);
        }
      }
      nextLoadPage++;
      Log.d(Tag, "nextLoadPage=" + nextLoadPage);
      if (adapter != null) {
        adapter.addData(list);
      } else {
//          novelList = list;
        novelList.clear();
        novelList.addAll(list);
      }
    }
  }

  @Override
  public void onFailure(Call<List<Novel>> call, Throwable t) {
    setLoading(false);
    setSwipeRefresh(false);
  }

  public void setSearchKey(String searchKey) {
    this.searchKey = searchKey;
    loadData();
  }

  private class MyOnRereshListener implements SwipeRefreshLayout.OnRefreshListener {
    @Override
    public void onRefresh() {
      loadData();
    }
  }

  private class MyOnScrollListener extends RecyclerView.OnScrollListener {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
      super.onScrolled(recyclerView, dx, dy);
      boolean hasLoadingMore = adapter.isHasLoadingMore();
      if (hasLoadingMore) {
        if (isLoading()) {
          return;
        }
        int lastVisiblePosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findLastVisibleItemPosition();
        if (adapter.getItemCount() > 0 && lastVisiblePosition + CommonUtil.LOAD_MORE_ITEM > adapter.getItemCount()) {
          Log.d(Tag, "lastVisiblePosition=" + lastVisiblePosition + ",current itemCount=" + adapter.getItemCount());
          setLoading(true);
          if (dataType == CommonUtil.NovelListType.TYPE_NOVEL_TOP) {
            loadNovelTopList(topType, nextLoadPage);
          } else if (dataType == CommonUtil.NovelListType.TYPE_NOVEL_CATEGORY) {
            loadCategoryNovelList(categoryId, nextLoadPage);
          } else if (dataType == CommonUtil.NovelListType.TYPE_NOVEL_SEARCH) {
            loadSearchNovelList(searchKey, nextLoadPage);
          }
        }
      }
    }

    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
      super.onScrollStateChanged(recyclerView, newState);
    }
  }
}
